/*
 * Copyright (c) 2012, Will Strohl
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * * Redistributions of source code must retain the above copyright notice, this 
 * list of conditions and the following disclaimer.
 * 
 * * Redistributions in binary form must reproduce the above copyright notice, this 
 * list of conditions and the following disclaimer in the documentation and/or other 
 * materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 * 
*/

using System.Collections.Generic;
//using System.Xml;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Content;
using DotNetNuke.Entities.Content.Common;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Services.Search;
using System;
using System.Linq;

namespace WillStrohl.Modules.BookmarkCollector.Components
{

    /// -----------------------------------------------------------------------------
    /// <summary>
    /// The Controller class for BookmarkCollector
    /// 
    /// The FeatureController class is defined as the BusinessController in the manifest file (.dnn)
    /// DotNetNuke will poll this class to find out which Interfaces the class implements. 
    /// 
    /// The IPortable interface is used to import/export content from a DNN module
    /// 
    /// The ISearchable interface is used by DNN to index the content of a module
    /// 
    /// The IUpgradeable interface allows module developers to execute code during the upgrade 
    /// process for a module.
    /// 
    /// Below you will find stubbed out implementations of each, uncomment and populate with your own data
    /// </summary>
    /// -----------------------------------------------------------------------------
    public class BookmarkController //: IPortable, ISearchable, IUpgradeable
    {

        #region Constants

        public const string BOOKMARK_MODULE_TYPE_NAME = "WillStrohl.Modules.BookmarkCollector";
        private const string CONTENT_FORMAT = "{0}|{1}";
        private const string CONTENT_KEY_FORMAT = "{0}|{1}|{2}";
        private const string SEPARATOR = "|";

        #endregion

        #region Private Members

        private int contentTypeId = Null.NullInteger;

        #endregion

        #region Content Item Helpers

        public int BookmarkContentTypeId
        {
            get
            {
                // just return the contentTypeId if it is already populated
                if (contentTypeId != Null.NullInteger) return contentTypeId;

                // create or query for a contentTypeId
                var typeController = new ContentTypeController();
                var colContentTypes =
                    (from t in typeController.GetContentTypes()
                     where t.ContentType == BOOKMARK_MODULE_TYPE_NAME
                     select t);

                if (colContentTypes.Any())
                {
                    var contentType = colContentTypes.Single();
                    contentTypeId = contentType == null ? CreateContentType() : contentType.ContentTypeId;
                }
                else
                {
                    contentTypeId = CreateContentType();
                }

                return contentTypeId;
            }
        }

        private static int CreateContentType()
        {
            var typeController = new ContentTypeController();
            var objContentType = new ContentType { ContentType = BOOKMARK_MODULE_TYPE_NAME };

            return typeController.AddContentType(objContentType);
        }

        #endregion

        #region Data Access

        public int CreateContentItem(int tabId, int moduleId, BookmarkInfo bookmark)
        {
            var objContent = new ContentItem
               {
                   Content = string.Format(CONTENT_FORMAT, bookmark.Title, bookmark.Url),
                   ContentTypeId = BookmarkContentTypeId,
                   Indexed = false,
                   ContentKey = string.Format(CONTENT_KEY_FORMAT, tabId, moduleId, bookmark.Id),
                   ModuleID = moduleId,
                   TabID = tabId
               };

            objContent.ContentItemId = Util.GetContentController().AddContentItem(objContent);

            // update the content item again since we now have a contentItemId
            objContent.ContentKey = string.Format(CONTENT_KEY_FORMAT, tabId, moduleId, objContent.ContentItemId);
            Util.GetContentController().UpdateContentItem(objContent);

            return objContent.ContentItemId;
        }

        public void UpdateContentItem(int tabId, int moduleId, int contentItemId, BookmarkInfo bookmark)
        {
            var objContent = Util.GetContentController().GetContentItem(contentItemId);

            if (objContent == null) return;

            objContent.Content = string.Format(CONTENT_FORMAT, bookmark.Title, bookmark.Url);
            objContent.ContentKey = string.Format(CONTENT_KEY_FORMAT, tabId, moduleId, contentItemId);
            objContent.ModuleID = moduleId;
            objContent.TabID = tabId;
            
            Util.GetContentController().UpdateContentItem(objContent);
        }

        public void DeleteContentItem(int contentItemId)
        {
            Util.GetContentController().DeleteContentItem(contentItemId);
        }

        public void DeleteContentItem(ContentItem contentItem)
        {
            Util.GetContentController().DeleteContentItem(contentItem);
        }

        public BookmarkInfo GetContentItem(int contentItemId)
        {
            var objContent = Util.GetContentController().GetContentItem(contentItemId);
            return ParseContentItemForBookmark(objContent);
        }

        public IList<BookmarkInfo> GetContentItems(int moduleId)
        {
            var collContent = (
                from t in Util.GetContentController().GetContentItemsByModuleId(moduleId)
                where t.ContentKey != string.Empty
                orderby t.Content
                select t);
            return ParseContentItemsForBookmarkCollection(collContent);
        }

        #endregion

        #region Helper Methods

        private BookmarkInfo ParseContentItemForBookmark(ContentItem contentItem)
        {
            var bookmark = new BookmarkInfo();
            bookmark.RawContent = contentItem.Content;

            var content = new string[3];
            content = bookmark.RawContent.Split(SEPARATOR.ToCharArray());

            bookmark.Id = contentItem.ContentItemId;
            bookmark.Title = content[0];
            bookmark.Url = content[1];

            return bookmark;
        }

        private IList<BookmarkInfo> ParseContentItemsForBookmarkCollection(IQueryable<ContentItem> contentItems)
        {
            var bookmarks = new List<BookmarkInfo>(contentItems.Count());

            foreach (ContentItem contentItem in contentItems)
            {
                BookmarkInfo bookmark = ParseContentItemForBookmark(contentItem);
                bookmarks.Add(bookmark);
            }

            return bookmarks;
        }

        #endregion

        #region Optional Interfaces

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// ExportModule implements the IPortable ExportModule Interface
        /// </summary>
        /// <param name="ModuleID">The Id of the module to be exported</param>
        /// -----------------------------------------------------------------------------
        //public string ExportModule(int ModuleID)
        //{
        //string strXML = "";

        //List<BookmarkCollectorInfo> colBookmarkCollectors = GetBookmarkCollectors(ModuleID);
        //if (colBookmarkCollectors.Count != 0)
        //{
        //    strXML += "<BookmarkCollectors>";

        //    foreach (BookmarkCollectorInfo objBookmarkCollector in colBookmarkCollectors)
        //    {
        //        strXML += "<BookmarkCollector>";
        //        strXML += "<content>" + DotNetNuke.Common.Utilities.XmlUtils.XMLEncode(objBookmarkCollector.Content) + "</content>";
        //        strXML += "</BookmarkCollector>";
        //    }
        //    strXML += "</BookmarkCollectors>";
        //}

        //return strXML;

        //	throw new System.NotImplementedException("The method or operation is not implemented.");
        //}

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// ImportModule implements the IPortable ImportModule Interface
        /// </summary>
        /// <param name="ModuleID">The Id of the module to be imported</param>
        /// <param name="Content">The content to be imported</param>
        /// <param name="Version">The version of the module to be imported</param>
        /// <param name="UserId">The Id of the user performing the import</param>
        /// -----------------------------------------------------------------------------
        //public void ImportModule(int ModuleID, string Content, string Version, int UserID)
        //{
        //XmlNode xmlBookmarkCollectors = DotNetNuke.Common.Globals.GetContent(Content, "BookmarkCollectors");
        //foreach (XmlNode xmlBookmarkCollector in xmlBookmarkCollectors.SelectNodes("BookmarkCollector"))
        //{
        //    BookmarkCollectorInfo objBookmarkCollector = new BookmarkCollectorInfo();
        //    objBookmarkCollector.ModuleId = ModuleID;
        //    objBookmarkCollector.Content = xmlBookmarkCollector.SelectSingleNode("content").InnerText;
        //    objBookmarkCollector.CreatedByUser = UserID;
        //    AddBookmarkCollector(objBookmarkCollector);
        //}

        //	throw new System.NotImplementedException("The method or operation is not implemented.");
        //}

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// GetSearchItems implements the ISearchable Interface
        /// </summary>
        /// <param name="ModInfo">The ModuleInfo for the module to be Indexed</param>
        /// -----------------------------------------------------------------------------
        //public DotNetNuke.Services.Search.SearchItemInfoCollection GetSearchItems(DotNetNuke.Entities.Modules.ModuleInfo ModInfo)
        //{
        //SearchItemInfoCollection SearchItemCollection = new SearchItemInfoCollection();

        //List<BookmarkCollectorInfo> colBookmarkCollectors = GetBookmarkCollectors(ModInfo.ModuleID);

        //foreach (BookmarkCollectorInfo objBookmarkCollector in colBookmarkCollectors)
        //{
        //    SearchItemInfo SearchItem = new SearchItemInfo(ModInfo.ModuleTitle, objBookmarkCollector.Content, objBookmarkCollector.CreatedByUser, objBookmarkCollector.CreatedDate, ModInfo.ModuleID, objBookmarkCollector.ItemId.ToString(), objBookmarkCollector.Content, "ItemId=" + objBookmarkCollector.ItemId.ToString());
        //    SearchItemCollection.Add(SearchItem);
        //}

        //return SearchItemCollection;

        //	throw new System.NotImplementedException("The method or operation is not implemented.");
        //}

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// UpgradeModule implements the IUpgradeable Interface
        /// </summary>
        /// <param name="Version">The current version of the module</param>
        /// -----------------------------------------------------------------------------
        //public string UpgradeModule(string Version)
        //{
        //	throw new System.NotImplementedException("The method or operation is not implemented.");
        //}

        #endregion

    }

}
